/****************************************************************************
Copyright (c) 2004 - 2017 Qualcomm Technologies International, Ltd.

FILE NAME
    audio.h

DESCRIPTION
    header file for the audio library
*/

/*!
\defgroup audio audio
\ingroup vm_libs

\brief  Header file for the audio library.
\section audio_intro INTRODUCTION
    This defines the Application Programming interface to the audio library.

    i.e. the interface between the VM application and the audio library.

    see the audio_plugin_if documentation for details of the API between the
    audio library and an underlying audio plugin.

@{

*/



#ifndef _AUDIO_H_
#define _AUDIO_H_

#include <message.h>
#include <stream.h> /*for the ringtone_note*/

#include <audio_plugin_if.h>
#include <audio_instance.h>

/*!  Audio Plugin Upstream Messages

    These messages are sent from the audio plugins to the client Task.

    Usually the audio plugins will not send upstream messages,
    but certain plugins will send information to the application.
*/
typedef enum
{
    AUDIO_DSP_IND = AUDIO_UPSTREAM_MESSAGE_BASE,
    AUDIO_DSP_READY_FOR_DATA,
    AUDIO_LATENCY_REPORT,
    AUDIO_GET_USER_EQ_PARAMETER_CFM,
    AUDIO_GET_USER_EQ_PARAMETERS_CFM,
    AUDIO_REFRESH_VOLUME,
    AUDIO_SIGNAL_DETECT_MSG,
    AUDIO_PROMPT_DONE,
    AUDIO_BA_RECEIVER_START_SCAN_VARIANT_IV,
    AUDIO_BA_RECEIVER_RESET_BD_ADDRESS,
    AUDIO_BA_RECEIVER_INDICATE_STREAMING_STATE,
    AUDIO_VA_INDICATE_DATA_SOURCE,
     /* Library message limit */
    AUDIO_UPSTREAM_MESSAGE_TOP
} audio_plugin_upstream_message_type_t;

/*!
    @brief This message is generated by an audio plugin module and sent to the application Task.
*/
typedef struct
{
    /*! The id of the message sent to the application */
    uint16          id ;
    /*! The number of values sent to the application */
    uint16          size_value;
    /*! The values sent to the application */
    uint16          value[1] ;
}AUDIO_DSP_IND_T ;


/*!
    @brief This message is generated by an audio plugin module and sent to the application Task
    to indicate that the DSP is ready to accept data and no audio will be lost .
*/
typedef struct
{
    /* main plugin in use */
    Task plugin;
    /* audio routing currently in progress */
    Task AUDIO_BUSY;
    /* current dsp status */
    DSP_STATUS_INFO_T dsp_status;
    /* sink of media used for a2dp connection */
    Sink media_sink;
}AUDIO_DSP_READY_FOR_DATA_T ;


/*!
    @brief This message is generated by an audio plugin module and sent to the application Task
    to report a change in audio decoder latency.
*/
typedef struct
{
    /* Flag indicating if latency value has been estimated (calculated) rather than measured */
    bool estimated;
    /* current audio latency, in tenths of milliseconds */
    uint16 latency;
    /* Media sink */
    Sink sink;
} AUDIO_LATENCY_REPORT_T;

/*!
    @brief This message is generated by speech recognition plug-in and sent to
    the application Task (as registered in AudioConnect) to report a speech
    recognition result.
*/
typedef enum
{
    CSR_SR_MESSAGE_BASE            = CSR_SPEECH_RECOGNITION_MESSAGE_BASE ,
    CSR_SR_WORD_RESP_YES     ,
    CSR_SR_WORD_RESP_NO      ,
    CSR_SR_WORD_RESP_FAILED_YES,
    CSR_SR_WORD_RESP_FAILED_NO,
    CSR_SR_WORD_RESP_UNKNOWN
} CsrSpeechRecognitionId ;

/* External mic settings, applicable to APTX ll + back channel application only */
#define EXTERNAL_MIC_NOT_FITTED 1
#define EXTERNAL_MIC_FITTED     2

typedef enum
{
    user_eq_param_type_filter,
    user_eq_param_type_cutoff_freq,
    user_eq_param_type_gain,
    user_eq_param_type_q
} user_eq_param_type_t;


typedef struct
{
    uint16 bank;
    uint16 band;
    user_eq_param_type_t param_type;
} user_eq_id_t;

typedef struct
{
    user_eq_id_t id;
    uint32 value;
} user_eq_param_t;


typedef struct
{
    /*! The values sent to the application */
    bool            data_valid;
    user_eq_param_t param[1] ;
}AUDIO_GET_USER_EQ_PARAMETER_CFM_T ;


typedef struct
{
    bool            data_valid;
    uint16          number_of_params;
    user_eq_param_t params[1] ;
}AUDIO_GET_USER_EQ_PARAMETERS_CFM_T ;


typedef struct
{
    bool signal_detected;
} AUDIO_SIGNAL_DETECT_MSG_T;

/*!
    @brief This message is generated by audio plugin module and sent to the application Task
    to report data source availabilty for voice assistant.
*/

typedef struct
{
    /* main plugin in use */
    Task plugin;
    /* voice assistant data source */
    Source data_src;
}AUDIO_VA_INDICATE_DATA_SOURCE_T;

/*!
    @brief  Malloc the memory to be used by the audio library
*/
void AudioLibraryInit (void);


/*!
    @brief Connects an audio stream to the underlying audio plugin

    @param audio_plugin The audio plugin to use for the audio connection
    @param audio_sink The Sink to connect (may be synchronous AV or other)
    @param sink_type The type of audio connection required - see AUDIO_SINK_T
    @param volume The volume at which to connect the audio plugin.
                  The plugin vendor is responsible for the use of this value
    @param rate The data bit rate
    @param features Whether or not a stereo connection is to be used (channel A or channel A & B)
    @param mode The mode to set the audio connection to
                This behaviour is plugin dependent
    @param route The route the audio will take (internal, i2s, spif)
                This behaviour is plugin dependent
    @param power The power level the plugin will use
                This behaviour is plugin dependent
    @param params Used to specify plugin specific parameters - See plugin vendor for details
    @param app_task The main application task that should receive messages sent from the plugin.

    The underlying audio plugin is responsible for connecting up the audio sink
    as requested

    Calls to AudioConnect will be queued if the AUDIO_BUSY flag is set.
    i.e. if a tone is currently being played, then the audio connection will occur
    once the tone has completed.
*/
audio_instance_t AudioConnect(Task audio_plugin,
                  Sink audio_sink ,
                  AUDIO_SINK_T sink_type ,
                  int16 volume,
                  uint32 rate  ,
                  AudioPluginFeatures features ,
                  AUDIO_MODE_T mode ,
                  AUDIO_ROUTE_T route ,
                  AUDIO_POWER_T power ,
                  void * params ,
                  Task app_task);


/*!
    @brief Disconnects the audio stream most recently connected using AudioConnect

    The most recent audio_plugin connected using AudioConnect()
    will be asked to perform the disconnect.

    Calls to AudioDisconnect when no plugin is connected will be ignored
*/
void AudioDisconnect(void);


/*!
    @brief Disconnects the audio stream associated with the specified audio instance

    The audio_plugin associated with the specified instance will be asked
    to perform the disconnect.

    Calls to AudioDisconnectInstance when no plugin is connected will be ignored
*/
void AudioDisconnectInstance(audio_instance_t instance);


/*!
    @brief Updates the volume of any currently connected audio connection

    @param volume The new volume to pass to the currently connected audio plugin
    @param tone_volume The new tone/prompt volume to pass to the currently connected audio plugin

    The volume is set by the underlying audio plugin and the behaviour is specific
    to the implementation of the plugin.

    Some plugins may interpret this as a codec gain
    Others may choose to ignore this value etc

    Note : the initial volume setting is passed in as part of AudioConnect
*/
void AudioSetVolume(int16 volume , int16 tone_volume);


/*!
    @brief Updates the mode of any currently connected audio connection

    @param mode The mode to set the audio connection to
                This behaviour is plugin dependent
    @param params Used to specify plugin specific parameters - See plugin vendor for details

    The mode can be used to change the connection behaviour of an underlying plugin and this
    behaviour is not supported by all plugin vendors.

    This call is ignored if no plugin is currently connected

    Note : The mode & params are passed in as part of AudioConnect
*/
bool AudioSetMode(AUDIO_MODE_T mode , void * params);


/*!
    @brief Updates the status of music processing functionality

    @param audio_processing_mode The required audio processing mode to switch to

    @param music_enhancements The music processing features to be enabled/disabled

    Note : The music_enhancements are passed in as part of AudioConnect
*/

bool AudioSetMusicProcessingEnhancements (A2DP_MUSIC_PROCESSING_T audio_processing_mode, uint16 music_enhancements);


/*!
    @brief Set the operating mode of the sub woofer

    @param sub_woofer_type

    @param sub_sink

    @return True if message was sent
*/
bool AudioConfigureSubWoofer(AUDIO_SUB_TYPE_T sub_woofer_type, Sink sub_sink );


/*!
    @brief Updates the mute state of the audio using soft mute

    @param mute_message Defines which mute type to apply

    This call is ignored if no plugin is currently connected
*/
bool AudioSetSoftMute(AUDIO_PLUGIN_SET_SOFT_MUTE_MSG_T* mute_message);


/*!
    @brief Starts forwarding undecoded audio frames to the specified sink

    @param relay_plugin Plugin that manages the relay mechanism
    @param forwarding_sink The media sink to a remote device
                           This behaviour is plugin dependent
    @param content_protection Flag indicating if content protection is enabled
    @param buffer_level Buffering level required
    @param output_plugin Output plugin

    This call is ignored if a main plugin is not currently connected
*/
bool AudioStartForwarding(Task relay_plugin, Sink forwarding_sink, bool content_protection, peer_buffer_level buffer_level, Task output_plugin);


/*!
    @brief Stops forwarding of undecoded audio frames
           This behaviour is plugin dependent

    This call is ignored if no plugin is currently connected
*/
void AudioStopForwarding(void);


/*!
    @brief Plays a tone

    @param tone The tone to be played
    @param can_queue Whether or not to queue the requested tone
    @param tone_volume The volume at which to play the tone (0 = play tone at current volume)
    @param features including Whether or not a stereo connection is to be used (channel A or channel A & B)

    Tone playback can be used when an audio connection is present or not. (plugin connected or not)

    When a plugin is not connected, csr_voice_prompts_plugin is used for standalone tone playback

    When a plugin is connected, the tone playback request will be passed to the currently connected plugin
    The underlying plugin is then responsible for connecting up the audio tone.
    Some plugins may choose to ignore tone requests in certain modes

    Tone queuing can be achieved using the can_queue parameter. If this is selected, then
    tones will be queued using the audio flag AUDIO_BUSY.
    Tones will be played back in the order they are requested.
*/
void AudioPlayTone ( const ringtone_note * tone , bool can_queue , int16 tone_volume , AudioPluginFeatures features ) ;


/*!
    @brief Stops a currently playing tone or audio prompt

    @param prompt_terminate If true, pending audio prompts will be cancelled and active audio prompts
                            will be ended prematurely. If false, audio prompt early termination is disabled.
                            Tones are always cancelled and ended prematurely.

    If a tone or audio prompt is currently connected to either the default tone plugin (csr_tone_plugin)
    or to any other connected plugin then, it can be stopped part way through.

    In general, this is used to end ring tones prematurely to allow fast call setup times.

    Note : The implementation of AudioStopToneAndPrompt is plugin specific.
    Some plugins may choose to ignore the request to stop playback of a tone
*/
void AudioStopToneAndPrompt ( bool prompt_terminate ) ;


/*!
    @brief Plays text-to-speech

    @param plugin Audio Prompt plugin to use

    @param prompt_index Index of the prm file for that prompt in the file system

    @param prompt_header_index Index of the idx file that corresponds to the prm file

    @param can_queue If this is TRUE, and Audio Prompt cannot currently be played
                (eg tone is playing), then it will be played on
                completion of the currently playing tone

    @param ap_volume The volume at which to play the Audio Prompt. A non-zero value will
                      cause the Audio Prompt to played at this volume level.

    @param features including Whether or not a stereo connection is to be used (channel A or channel A & B)

    @param app_task The main application task that should receive messages sent from audio lib.

    @param override  prompt is set to play immediately, cancel any queued prompts
*/
void AudioPlayAudioPrompt ( Task plugin, FILE_INDEX prompt_index, FILE_INDEX prompt_header_index, bool can_queue, int16 ap_volume, AudioPluginFeatures features, bool override, Task app_task );


/*!
    @brief Updates the Power level of any currently connected audio connection

    @param power The power to set the audio connection to
                This behaviour is plugin dependent

    This can be used to change the power level of an underlying plugin and this
    behaviour is not supported by all plugin vendors.

    This call is ignored if no plugin is currently connected
*/
void AudioSetPower(AUDIO_POWER_T power);


/*!
    @brief Used in production Testing to swap between microphone inputs
*/
void AudioMicSwitch ( void );


/*!
    @brief Used in production Testing to swap outputs
*/
void AudioOutputSwitch(void);


/*!
    @brief Start or restart the ASR algorithm

    @return True if successful
*/
bool AudioStartASR ( AUDIO_MODE_T mode ) ;


/*!
    @brief Gets the audio_busy flag

    @return The current state of the audio_busy flag
*/
bool IsAudioBusy(void);


/*!
    @brief Query the current status of the audio library

    @return Pointer to current audio_busy task value
*/
Task AudioBusyTask(void);


/*!
    @brief Update the current status of the audio library

    @param task The current audio task
*/
void SetAudioBusy(TaskData* task);


/*!
    @brief query the current dsp status of the audio library

    @return pointer to current dsp status value
*/
DSP_STATUS_INFO_T GetCurrentDspStatus(void);


/*!
    @brief update the current dsp status of the audio library

    @param status The new dsp status
*/
void SetCurrentDspStatus(DSP_STATUS_INFO_T status);


/*!
    @brief uery whether the audio sub system is currently in use

    @return True if audio is in use
*/
bool IsAudioInUse(void);


/*!
    @brief Update the current audio in use state

    @param status The new audio in use state
*/
void SetAudioInUse(bool status);

/*!
    @brief Update the current relay_plugin variable

    @param plugin The active relay plugin
*/
void AudioSetRelayPlugin(Task plugin);

/*!
    @brief Set the plugin associated with current prompt playback

    @param plugin plugin responsible for playback of the current
    tone or voice prompt
*/
void AudioSetAudioPromptPlayingTask(Task plugin);

/*!
    @brief Get the plugin associated with current prompt playback
*/
Task AudioGetAudioPromptPlayingTask(void);

/*!
    @brief Query whether a tone or voice prompt is currently playing

    @return True if a tone or voice prompt is playing
*/
bool AudioIsAudioPromptPlaying(void);

/*!
    @brief Query whether the  plugin used for the stream relay operation is available

    @return True if relay functionalitry is available
*/
bool IsAudioRelaying(void);

/*!
    @brief query whether the asr system is currently in use

    @return True if playing

*/
bool IsAsrPlaying(void);


/*!
    @brief update the current asr state

    @param status The new ASR status

*/
void SetAsrPlaying(bool status);

/*!
    @brief Get pointer to AUDIO_BUSY for use with messageSendConditionally

    @return Pointer to current audio_busy task value

*/
const Task * AudioBusyPtr(void);

/*!
    @brief Compare the control plugin with supplied parameter

    @param plugin_to_check plugin to test against

    @return True if plugin_to_check matches

    This method compares the supplied parameter with the plugin that the last AudioConnect()
    call was made to, and returns true if they match.
*/
bool AudioIsControlPlugin(Task plugin_to_check);

/*!
    @brief Overrides the audio plugin responsible for handling messages sent from the audio library

    Control plugin is set whenever a successful call to AudioConnect is made, this function
    allows the sink app to override this.
*/
void AudioOverrideControlPlugin(Task plugin);

/*!
    @brief Returns the plugin associated with tones and voice prompts

    @return tone/voice prompt plugin
*/
Task AudioGetTonePlugin(void);

/*!
    @brief Set group volume in increments of 60th of dB.

    @param msg Pointer to the preconstructed message
*/
void AudioSetGroupVolume(AUDIO_PLUGIN_SET_GROUP_VOLUME_MSG_T *msg);

/*!
    @brief Mute / unmute the input audio port for all the audio sources except tones.

    @param enable - True to mute/false to unmute
*/
void AudioSetInputAudioMute (bool enable);

/*!
    @brief Reads estimated or actual link latency.

    @param audio_plugin The plugin for which the latency is being got.
    @param estimated Set to TRUE if the plugin is estimating the latency.
    @param latency Set to playback latency in 1/10th milliseconds.

    @return True if read of latency was sucessful.
*/
bool AudioGetLatencyInTenthsOfMilliseconds(Task audio_plugin, bool *estimated, uint16 *latency);

/*!
    @brief Get Usb plugin sample rate

    @return The USB sampling rate
*/
uint32 AudioGetUsbSampleRate(void);

/*!
    @brief Get subwoofer sampling rate

    @return The subwoofer sampling rate
*/
uint32 AudioGetA2DPSubwooferSampleRate(void);

/*!
    @brief Sets the number of concurrent audio connections the application supports.

    @param connections The number of supported concurrent connections

    Note: The library must also be able to support this number.
*/
void AudioSetMaximumConcurrentAudioConnections(unsigned connections);

/*!
    @brief Sets an individual user peq parameter.

    @param param data that describes the PEQ parameter

    @param reclalc A bool that determines whether the dsp should recalculate dsp parameters

    @return A boolean indicating whether the message was sent or not

    Note: It is only possible to update user peq bank 1
*/
bool AudioSetUserEqParameter(const Task task, const audio_plugin_user_eq_param_t* param);

/*!
    @brief Applies the stored set of eq parameters and clears the store.
*/
bool AudioApplyUserEqParameters(const Task task, bool recalculate_coefficients);

/*!
    @brief Clears the stored set of eq parameters.
*/
bool AudioClearUserEqParameters(const Task task);

/*!
    @brief Gets a user peq parameter.

    This method sends a get parameter message to the dsp, which is handled seperately
*/
bool AudioGetUserEqParameter(const Task task, const audio_plugin_user_eq_param_id_t* param, Task callback_task);

/*!
    @brief Gets a group of user peq parameters.

    This method sends a get parameter message to the dsp, which is handled seperately
*/
bool AudioGetUserEqParameters(const Task task, const unsigned number_of_params, const audio_plugin_user_eq_param_id_t* params, Task callback_task);

/*!
    @brief Sets the Speaker PEQ Bypass, The speaker peq is only updated upon mixer chain initialisation, and not dynamically.

    @param speaker_peq_bypass Speaker PEQ is bypassed or not.
*/
void AudioSetSpeakerPeqBypass(bool speaker_peq_bypass);

/*!
    @brief Set the required channel mode for music inputs.

    This method sends a SetChannelMode message to the specified task
*/
bool AudioSetTwsChannelModes(const Task task, const AUDIO_MUSIC_CHANNEL_MODE_T channel_mode_master, const AUDIO_MUSIC_CHANNEL_MODE_T channel_mode_slave);

/*!
    @param app_task The main application task that should receive messages sent from the plugin.

    @return A boolean indicating whether the method accepted the request or not

*/
bool AudioStartVoiceCapture (Task app_task);

/*!
    @brief Stop Capturing Voice

    @return A boolean indicating whether the method accepted the request or not

*/
bool AudioStopVoiceCapture(void);

#ifdef HOSTED_TEST_ENVIRONMENT
/*!
    @brief Reset the audio library

    Reset the audio library of an audio_plugin. Note that plug-in must
    support the message AUDIO_PLUGIN_TEST_RESET_MSG for this to work. This is
    only intended for unit test and will panic if called in a release build.
*/
void AudioLibraryTestReset(Task audio_plugin);
#endif

#endif /* _AUDIO_H_ */

/** @} */
